#ifndef TYPEMANIP_INC_
#define TYPEMANIP_INC_

namespace XGC
{
namespace common
{
	struct NullType
	{
	};
////////////////////////////////////////////////////////////////////////////////
// class template Int2Type
// Converts each integral constant into a unique type
// Invocation: Int2Type<v> where v is a compile-time constant integral
// Defines 'value', an enum that evaluates to v
////////////////////////////////////////////////////////////////////////////////

    template <int v>
    struct Int2Type
    {
        enum { value = v };
    };
    
////////////////////////////////////////////////////////////////////////////////
// class template Type2Type
// Converts each type into a unique, insipid type
// Invocation Type2Type<T> where T is a type
// Defines the type OriginalType which maps back to T
////////////////////////////////////////////////////////////////////////////////

    template <typename T>
    struct Type2Type
    {
        typedef T OriginalType;
    };
    
	template <typename H, typename T>
	struct TypeList
	{
		typedef H Head;
		typedef T Tail;
	};

	template< XGC_ENUM( 32, class T, = NullType XGC_COMMA ) = NullType >
	struct TypeSequence
	{
	private:
		typedef typename TypeSequence< XGC_ENUM_NOHEAD( 32, T, XGC_COMMA ) >::Result TailResult;

	public:
		typedef TypeList<T1, TailResult> Result;
	};

	template<>
	struct TypeSequence<>
	{
		typedef NullType Result;
	};

	//////////////////////////////////////////////////////////////////////////
	// type list operator
	//////////////////////////////////////////////////////////////////////////
	template <class TList> struct Length;
	template <> struct Length<NullType>
	{
		enum { value = 0 };
	};

	template <class T, class U>
	struct Length< TypeList<T, U> >
	{
		enum { value = 1 + Length<U>::value };
	};

	//////////////////////////////////////////////////////////////////////////
	template <class TList, unsigned int index> struct TypeAt;

	template <class Head, class Tail>
	struct TypeAt<TypeList<Head, Tail>, 0>
	{
		typedef Head Result;
	};

	template <class Head, class Tail, unsigned int i>
	struct TypeAt<TypeList<Head, Tail>, i>
	{
		typedef typename TypeAt<Tail, i - 1>::Result Result;
	};

	//////////////////////////////////////////////////////////////////////////
	template <class TList, class T> struct IndexOf;

	template <class T>
	struct IndexOf<NullType, T>
	{
		enum { value = -1 };
	};

	template <class T, class Tail>
	struct IndexOf<TypeList<T, Tail>, T>
	{
		enum { value = 0 };
	};

	template <class Head, class Tail, class T>
	struct IndexOf<TypeList<Head, Tail>, T>
	{
	private:
		enum { temp = IndexOf<Tail, T>::value };
	public:
		enum { value = (temp == -1 ? -1 : 1 + temp) };
	};

	//////////////////////////////////////////////////////////////////////////
	template <class TList, class T> struct Append;

	template <> struct Append<NullType, NullType>
	{
		typedef NullType Result;
	};

	template <class T> struct Append<NullType, T>
	{
		typedef TypeList<T,NullType> Result;
	};

	template <class Head, class Tail>
	struct Append<NullType, TypeList<Head, Tail> >
	{
		typedef TypeList<Head, Tail> Result;
	};

	template <class Head, class Tail, class T>
	struct Append<TypeList<Head, Tail>, T>
	{
		typedef TypeList<Head,
			typename Append<Tail, T>::Result>
			Result;
	};

	//////////////////////////////////////////////////////////////////////////
	template <class TList, class T> struct Erase;

	template <class T>                         // Specialization 1
	struct Erase<NullType, T>
	{
		typedef NullType Result;
	};

	template <class T, class Tail>             // Specialization 2
	struct Erase<TypeList<T, Tail>, T>
	{
		typedef Tail Result;
	};

	template <class Head, class Tail, class T> // Specialization 3
	struct Erase<TypeList<Head, Tail>, T>
	{
		typedef TypeList<Head,
			typename Erase<Tail, T>::Result>
			Result;
	};

	template <class TList, class T> struct EraseAll;
	template <class T>
	struct EraseAll<NullType, T>
	{
		typedef NullType Result;
	};
	template <class T, class Tail>
	struct EraseAll<TypeList<T, Tail>, T>
	{
		// Go all the way down the list removing the type
		typedef typename EraseAll<Tail, T>::Result Result;
	};
	template <class Head, class Tail, class T>
	struct EraseAll<TypeList<Head, Tail>, T>
	{
		// Go all the way down the list removing the type
		typedef TypeList<Head,
			typename EraseAll<Tail, T>::Result>
			Result;
	};

	//////////////////////////////////////////////////////////////////////////
	template <class TList> struct RemoveDuplicates;

	template <> struct RemoveDuplicates<NullType>
	{
		typedef NullType Result;
	};

	template <class Head, class Tail>
	struct RemoveDuplicates< TypeList<Head, Tail> >
	{
	private:
		typedef typename RemoveDuplicates<Tail>::Result L1;
		typedef typename Erase<L1, Head>::Result L2;
	public:
		typedef TypeList<Head, L2> Result;
	};

////////////////////////////////////////////////////////////////////////////////
// class template Select
// Selects one of two types based upon a boolean constant
// Invocation: Select<flag, T, U>::Result
// where:
// flag is a compile-time boolean constant
// T and U are types
// Result evaluates to T if flag is true, and to U otherwise.
////////////////////////////////////////////////////////////////////////////////

    template <bool flag, typename T, typename U>
    struct choice
    {
        typedef T Result;
    };

    template <typename T, typename U>
    struct choice<false, T, U>
    {
        typedef U Result;
    };
    
////////////////////////////////////////////////////////////////////////////////
// class template IsSameType
// Return true iff two given types are the same
// Invocation: SameType<T, U>::value
// where:
// T and U are types
// Result evaluates to true iff U == T (types equal)
////////////////////////////////////////////////////////////////////////////////

    template <typename T, typename U>
    struct IsSameType
    {
        enum { value = false };
    };
    
    template <typename T>
    struct IsSameType<T,T>
    {
        enum { value = true };
    };

////////////////////////////////////////////////////////////////////////////////
// Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big)
////////////////////////////////////////////////////////////////////////////////

    namespace Private
    {
        template <class T, class U>
        struct ConversionHelper
        {
            typedef char Small;
            struct Big { char dummy[2]; };
            static Big   Test(...);
            static Small Test(U);
            static T MakeT();
        };
    }

////////////////////////////////////////////////////////////////////////////////
// class template Conversion
// Figures out the conversion relationships between two types
// Invocations (T and U are types):
// a) Conversion<T, U>::exists
// returns (at compile time) true if there is an implicit conversion from T
// to U (example: Derived to Base)
// b) Conversion<T, U>::exists2Way
// returns (at compile time) true if there are both conversions from T
// to U and from U to T (example: int to char and back)
// c) Conversion<T, U>::sameType
// returns (at compile time) true if T and U represent the same type
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////

    template <class T, class U>
    struct Conversion
    {
        typedef Private::ConversionHelper<T, U> H;
#ifndef __MWERKS__
        enum { exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))) };
#else
        enum { exists = false };
#endif
        enum { exists2Way = exists && Conversion<U, T>::exists };
        enum { sameType = false };
    };
    
    template <class T>
    struct Conversion<T, T>    
    {
        enum { exists = 1, exists2Way = 1, sameType = 1 };
    };
    
    template <class T>
    struct Conversion<void, T>    
    {
        enum { exists = 0, exists2Way = 0, sameType = 0 };
    };
    
    template <class T>
    struct Conversion<T, void>    
    {
        enum { exists = 0, exists2Way = 0, sameType = 0 };
    };
    
    template <>
    struct Conversion<void, void>    
    {
    public:
        enum { exists = 1, exists2Way = 1, sameType = 1 };
    };

////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclass
// Invocation: SuperSubclass<B, D>::value where B and D are types. 
// Returns true if B is a public base of D, or if B and D are aliases of the 
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////

template <class T, class U>
struct SuperSubclass
{
    enum { value = (::XGC::common::Conversion<const volatile U*, const volatile T*>::exists &&
                  !::XGC::common::Conversion<const volatile T*, const volatile void*>::sameType) };
      
    // Dummy enum to make sure that both classes are fully defined.
    enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) };
};

template <>
struct SuperSubclass<void, void> 
{
    enum { value = false };
};

template <class U>
struct SuperSubclass<void, U> 
{
    enum { value = (::XGC::common::Conversion<const volatile U*, const volatile void*>::exists &&
                  !::XGC::common::Conversion<const volatile void*, const volatile void*>::sameType) };
      
    // Dummy enum to make sure that both classes are fully defined.
    enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) };
};

template <class T>
struct SuperSubclass<T, void> 
{
    enum { value = (::XGC::common::Conversion<const volatile void*, const volatile T*>::exists &&
                  !::XGC::common::Conversion<const volatile T*, const volatile void*>::sameType) };
      
    // Dummy enum to make sure that both classes are fully defined.
    enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) };
};

////////////////////////////////////////////////////////////////////////////////
// class template SuperSubclassStrict
// Invocation: SuperSubclassStrict<B, D>::value where B and D are types. 
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
////////////////////////////////////////////////////////////////////////////////

template<class T,class U>
struct SuperSubclassStrict
{
    enum { value = (::XGC::common::Conversion<const volatile U*, const volatile T*>::exists &&
                 !::XGC::common::Conversion<const volatile T*, const volatile void*>::sameType &&
                 !::XGC::common::Conversion<const volatile T*, const volatile U*>::sameType) };
    
    // Dummy enum to make sure that both classes are fully defined.
    enum{ dontUseWithIncompleteTypes = ( sizeof (T) == sizeof (U) ) };
};

template<>
struct SuperSubclassStrict<void, void> 
{
    enum { value = false };
};

template<class U>
struct SuperSubclassStrict<void, U> 
{
    enum { value = (::XGC::common::Conversion<const volatile U*, const volatile void*>::exists &&
                 !::XGC::common::Conversion<const volatile void*, const volatile void*>::sameType &&
                 !::XGC::common::Conversion<const volatile void*, const volatile U*>::sameType) };
    
    // Dummy enum to make sure that both classes are fully defined.
    enum{ dontUseWithIncompleteTypes = ( 0 == sizeof (U) ) };
};

template<class T>
struct SuperSubclassStrict<T, void> 
{
    enum { value = (::XGC::common::Conversion<const volatile void*, const volatile T*>::exists &&
                 !::XGC::common::Conversion<const volatile T*, const volatile void*>::sameType &&
                 !::XGC::common::Conversion<const volatile T*, const volatile void*>::sameType) };
    
    // Dummy enum to make sure that both classes are fully defined.
    enum{ dontUseWithIncompleteTypes = ( sizeof (T) == 0 ) };
};


}   // namespace Loki
}
////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS
// Invocation: SUPERSUBCLASS(B, D) where B and D are types. 
// Returns true if B is a public base of D, or if B and D are aliases of the 
// same type.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
// Deprecated: Use SuperSubclass class template instead.
////////////////////////////////////////////////////////////////////////////////

#define SUPERSUBCLASS(T, U) \
    ::XGC::common::SuperSubclass<T,U>::value

////////////////////////////////////////////////////////////////////////////////
// macro SUPERSUBCLASS_STRICT
// Invocation: SUPERSUBCLASS(B, D) where B and D are types. 
// Returns true if B is a public base of D.
//
// Caveat: might not work if T and U are in a private inheritance hierarchy.
// Deprecated: Use SuperSubclassStrict class template instead.
////////////////////////////////////////////////////////////////////////////////

#define LOKI_SUPERSUBCLASS_STRICT(T, U) \
    ::XGC::common::SuperSubclassStrict<T,U>::value


#endif // end file guardian

